using System;
using System.Runtime.InteropServices;
using System.Drawing.Printing;
using System.Security.Permissions;
using System.Collections.ObjectModel;


namespace qPrintComponent
{
    public class qSafeDriverInfos : qSafeInfo
    {
        private string _servername;
        private System.Collections.Generic.Dictionary<string, qSafeDriverInfo> _collection; 
        private int recordcount;

        internal qSafeDriverInfos(string ServerName, int level)
            : base(IntPtr.Zero, level)
        {
            _servername = ServerName;
            RefreshInfo();
        }

        [PrintingPermission(SecurityAction.Demand, Level = PrintingPermissionLevel.DefaultPrinting)]
        protected override void RefreshInfo()
        {
            _collection = null;
            if (!qStatic.EnumPrinterDrivers(_servername, null, Level, handle, Size, out BytesNeeded, out recordcount) && (BytesNeeded > 0))
            {
                AllocMem();
                if (!qStatic.EnumPrinterDrivers(_servername, null, Level, handle, Size, out BytesNeeded, out recordcount) )
                    throw new System.ComponentModel.Win32Exception("DriverInfo" + Level.ToString(System.Globalization.CultureInfo.InvariantCulture) + " Error");
            }
        }

        protected override bool Update()
        {
            throw new NotImplementedException();
        }

        internal qSafeDriverInfo[] nDrivers
        {
            get
            {
                qSafeDriverInfo[]  _collection = new qSafeDriverInfo[this.recordcount];
                IntPtr ptr = base.handle;
                for (int i = 1; i <= this.recordcount; i++)
                {
                    switch (this.Level)
                    {
                        case 1:
                            _collection[i-1] = new DriverInfo1(ptr);
                            //size = 1
                            ptr = new IntPtr(base.handle.ToInt32() + (i * this.IntPtrSize * 1));
                            break;
                        case 2:
                            _collection[i-1] = new DriverInfo2(ptr);
                            //size = 6
                            ptr = new IntPtr(base.handle.ToInt32() + (i * this.IntPtrSize * 6));
                            break;
                        default:
                            return null;
                    }
                }
            return _collection;
            }
        }
    

        internal System.Collections.Generic.Dictionary<string, qSafeDriverInfo> Drivers
        {
            get
            {
                if (_collection == null)
                {
                    _collection = new System.Collections.Generic.Dictionary<string, qSafeDriverInfo>(this.recordcount);
                    IntPtr ptr = base.handle;
                    IntPtr qtr = IntPtr.Zero;
                    for (int i = 1; i <= this.recordcount; i++)
                    {
                        if (this.Level == 1)
                            qtr = Marshal.ReadIntPtr(ptr);
                        else
                            qtr = Marshal.ReadIntPtr(ptr, IntPtrSize);

                        if(qtr== IntPtr.Zero)
                        {
                            break;
                        }
                        switch (this.Level)
                        {
                            case 1:
                                _collection.Add(Marshal.PtrToStringUni(qtr), new DriverInfo1(ptr));
                                ptr = new IntPtr(base.handle.ToInt64() + (i * this.IntPtrSize * 1));
                                break;
                            case 2:
                                _collection.Add(Marshal.PtrToStringUni(qtr), new DriverInfo2(ptr));
                                ptr = new IntPtr(base.handle.ToInt64() + (i * this.IntPtrSize * 6));
                                break;
                            case 3:
                                _collection.Add(Marshal.PtrToStringUni(qtr), new DriverInfo3(ptr));
                                ptr = new IntPtr(base.handle.ToInt64() + (i * this.IntPtrSize * 10));
                                break;
                            case 4:
                                _collection.Add(Marshal.PtrToStringUni(qtr), new DriverInfo4(ptr));
                                ptr = new IntPtr(base.handle.ToInt64() + (i * this.IntPtrSize * 11));
                                break;
                            case 5:
                                _collection.Add(Marshal.PtrToStringUni(qtr), new DriverInfo5(ptr));
                                ptr = new IntPtr(base.handle.ToInt64() + (i * this.IntPtrSize * 9));
                                break;
                            case 6:
                                _collection.Add(Marshal.PtrToStringUni(qtr), new DriverInfo6(ptr));
                                ptr = new IntPtr(base.handle.ToInt64() + (i * this.IntPtrSize * 20));
                                break;
                            //case 8:
                            //    _collection.Add(Marshal.PtrToStringUni(qtr), new DriverInfo8(ptr));
                            //    ptr = new IntPtr(base.handle.ToInt32() + (i * this.IntPtrSize * 30));
                            //    break;
                            default:
                                return null;
                        }
                    }
                }
                return _collection;
            }
        }   
    }
}
